﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XMX.FileTransmit;

namespace TestXmodem_1K
{
    public class FileSend
    {
        public enum FileTransmitMode : int
        {
            ASCII = 0,
            Binary,
            Xmodem,
            Xmodem_1K,
            Ymodem,
            Ymodem_1K
        }
        private readonly int ReTryMax = 10;
        DateTime startTime;
        FileTransmitMode _FileTransMode = FileTransmitMode.ASCII;

        IFileTramsmit FileTransProtocol;
        private int fileIndex = 0;
        private int packetNo = 0;
        private byte[] PacketBuff;
        private int PacketLen = 128;

        public event EventHandler StartTransmitFile;
        public event EventHandler EndTransmitFile;
        public event SendToUartEventHandler SendToUartEvent;
        public string Filepaths = string.Empty;
        public FileSend()
        {
            
        }

        public void Start(string Filepath)
        {
            Filepaths = Filepath;
            FileTransProtocol = new XModem(TransmitMode.Send, XModemType.XModem_1K, 1024);
                
           

            if (FileTransProtocol != null)
            {
                FileTransProtocol.EndOfTransmit += new EventHandler(FileTransProtocol_EndOfTransmit);
                FileTransProtocol.AbortTransmit += new EventHandler(FileTransProtocol_AbortTransmit);
                FileTransProtocol.ReSendPacket += new EventHandler(FileTransProtocol_ReSendPacket);
                FileTransProtocol.SendNextPacket += new EventHandler(FileTransProtocol_SendNextPacket);
                FileTransProtocol.TransmitTimeOut += new EventHandler(FileTransProtocol_TransmitTimeOut);
                FileTransProtocol.StartSend += new EventHandler(FileTransProtocol_StartSend);
                FileTransProtocol.SendToUartEvent += new SendToUartEventHandler(FileTransProtocol_SendToUartEvent);

            }

            packetNo = 1;
            fileIndex = 0;
            FileTransProtocol.Start();

            if (StartTransmitFile != null)
            {
                StartTransmitFile(this, null);
            }
        }

        public void Stop()
        {
            if (FileTransProtocol != null)
            {
                FileTransProtocol.Abort();
            }

            SetEndTransmit();

           
        }

        public void ReceivedFromUart(byte[] data)
        {
            if (FileTransProtocol != null)
            {
                FileTransProtocol.ReceivedFromUart(data);
            }
        }


        

        
        private void SetEndTransmit()
        {
            

            if (EndTransmitFile != null)
            {
                EndTransmitFile(this, null);
            }

        }

        private int ReadPacketFromFile(int filePos, byte[] data, int packetLen)
        {

            FileStream fs = null;
            BinaryReader br = null;
            
            try
            {
                fs = new FileStream(Filepaths, FileMode.Open, FileAccess.Read);
                br = new BinaryReader(fs);

                if (filePos < fs.Length)
                {
                    fs.Seek(filePos, SeekOrigin.Begin);
                    int len = br.Read(data, 0, packetLen);

                    //ShowProgressReport(true, filePos, (int)fs.Length);

                    return len;
                }
                else
                {
                    return 0;
                }
            }
            catch (Exception ex)
            {
                throw ex;
                //MessageBox.Show(ex.Message, oFileDlg.Title, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                if (br != null) br.Close();
                if (fs != null) fs.Close();
            }
        }

        private byte[] ReadAllFromFile()
        {
            FileStream fs = null;
            BinaryReader br = null;
            
            try
            {
                fs = new FileStream(Filepaths, FileMode.Open, FileAccess.Read);
                br = new BinaryReader(fs);

                byte[] bytes = new byte[(UInt32)fs.Length];
                br.Read(bytes, 0, bytes.Length);

                return bytes;
            }
            catch (Exception ex)
            {
                throw ex;
                //MessageBox.Show(ex.Message, oFileDlg.Title, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                if (br != null) br.Close();
                if (fs != null) fs.Close();
            }
        }

        private string ReadLineFromFile()
        {
            string line = "";
            FileStream fs = null;
            StreamReader sr = null;
            // BinaryReader br = new BinaryReader(fs);
            try
            {
                fs = new FileStream(Filepaths, FileMode.Open, FileAccess.Read);
                sr = new StreamReader(fs, Encoding.Default);

                if (fileIndex < fs.Length)
                {
                    fs.Seek(fileIndex, SeekOrigin.Begin);

                    int chValue;
                    char c;

                    while (true)
                    {
                        chValue = sr.Peek();
                        if (chValue != 13 && chValue != 10)
                        {
                            break;
                        }
                        else
                        {
                            chValue = sr.Read();
                            c = Convert.ToChar(chValue);
                            fileIndex++;
                            //if (chkSendCRRF.Checked)
                            //{
                            //    line += c;
                            //}
                        }
                    }

                    string str = sr.ReadLine();

                    if (str != null)
                    {
                        fileIndex += System.Text.ASCIIEncoding.Default.GetBytes(str).Length;
                        line += str;
                    }



                    while (true)
                    {
                        chValue = sr.Peek();
                        if (chValue != 13 && chValue != 10)
                        {
                            break;
                        }
                        else
                        {
                            chValue = sr.Read();
                            c = Convert.ToChar(chValue);
                            fileIndex++;
                            //if (chkSendCRRF.Checked)
                            //{
                            //    line += c;
                            //}
                        }
                    }
                    

                }
                else
                {
                    return null;
                }

               
                return line;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (sr != null) sr.Close();
                if (fs != null) fs.Close();
            }
        }

        void FileTransProtocol_SendToUartEvent(object sender, SendToUartEventArgs e)
        {
            if (SendToUartEvent != null)
            {
                SendToUartEvent(sender, e);
            }
        }

        void FileTransProtocol_StartSend(object sender, EventArgs e)
        {
            PacketBuff = new byte[PacketLen];

            if (_FileTransMode == FileTransmitMode.Xmodem || _FileTransMode == FileTransmitMode.Xmodem_1K)
            {
                packetNo = 1;

                if (ReadPacketFromFile(fileIndex, PacketBuff, PacketLen) <= 0)
                {
                    FileTransProtocol.Stop();
                }
                else
                {
                    FileTransProtocol.SendPacket(new PacketEventArgs(packetNo, PacketBuff));
                }
                startTime = DateTime.Now;
            }
            else if (_FileTransMode == FileTransmitMode.Ymodem || _FileTransMode == FileTransmitMode.Ymodem_1K)
            {
                packetNo = 0;

                FileInfo fileInfo = new FileInfo(Filepaths);

                byte[] fileNameBytes = System.Text.ASCIIEncoding.Default.GetBytes(fileInfo.Name);

                int index = 0;
                Array.Copy(fileNameBytes, 0, PacketBuff, 0, fileNameBytes.Length);
                index += fileNameBytes.Length;
                PacketBuff[index] = 0;
                index++;
                byte[] fileSizeBytes = System.Text.ASCIIEncoding.Default.GetBytes(fileInfo.Length.ToString());
                Array.Copy(fileSizeBytes, 0, PacketBuff, index, fileSizeBytes.Length);

                FileTransProtocol.SendPacket(new PacketEventArgs(0, PacketBuff));

                fileIndex = 0;
                packetNo = 0;

                //fileInfo.Name;
                startTime = DateTime.Now;
            }

            //ShowTextReprot(string.Format("开始发送数据"));
        }

        void FileTransProtocol_TransmitTimeOut(object sender, EventArgs e)
        {
            
            SetEndTransmit();
        }

        void FileTransProtocol_SendNextPacket(object sender, EventArgs e)
        {

            
            if (_FileTransMode == FileTransmitMode.ASCII)
            {
                if (packetNo == 1)
                {
                    startTime = DateTime.Now;
                }
            }
            else if (_FileTransMode == FileTransmitMode.Binary)
            {
                if (packetNo == 1)
                {
                    startTime = DateTime.Now;
                    fileIndex = 0;
                }

                
            }
            else
            {
                PacketBuff = new byte[PacketLen];
                packetNo++;
                fileIndex += PacketLen;

                if (packetNo == 1)
                {
                    fileIndex = 0;
                }

                int readBytes = ReadPacketFromFile(fileIndex, PacketBuff, PacketLen);
                if (readBytes <= 0)
                {
                    FileTransProtocol.Stop();
                }
                else
                {
                    if (_FileTransMode == FileTransmitMode.Ymodem || _FileTransMode == FileTransmitMode.Ymodem_1K)
                    {
                        if (readBytes < PacketLen)
                        {
                            for (int i = readBytes; i < PacketLen; i++)
                            {
                                PacketBuff[i] = 0x1A;
                            }
                        }
                    }
                    FileTransProtocol.SendPacket(new PacketEventArgs(packetNo, PacketBuff));

                }
            }


        }

        void FileTransProtocol_ReSendPacket(object sender, EventArgs e)
        {
            FileTransProtocol.SendPacket(new PacketEventArgs(packetNo, PacketBuff));
            
        }

        void FileTransProtocol_AbortTransmit(object sender, EventArgs e)
        {
            SetEndTransmit();
        }

        void FileTransProtocol_EndOfTransmit(object sender, EventArgs e)
        {
            SetEndTransmit();

            
           
        }

       

        

        
    }
}
